#pragma once
#include <vector>

namespace RSA
{
	typedef unsigned char uint8;
	typedef unsigned long uint32;

	struct md5_context
	{
		uint32  total[2];
		uint32  state[4];
		uint8   buffer[64];
	};

	void __fastcall md5_starts( md5_context *ctx );
	void __fastcall md5_update( md5_context *ctx, const uint8 *input, uint32 length );
	void __fastcall md5_finish( md5_context *ctx, uint8 *digest );

	class MD5
	{
	public:
                MD5();
				MD5( const std::vector<char> &buf);
		void	update(const std::vector<char> &buf);
		void	update(const char *buf, uint32 length);
		void	finish(std::vector<char> &digest);

	private:
		md5_context context;
	};

	inline MD5::MD5()
	{   md5_starts( &context ); }

	inline MD5::MD5(const std::vector<char> &buf)
	{
		md5_starts( &context );
		md5_update( &context, reinterpret_cast<const uint8*>( &buf[0] ), static_cast<uint32>( buf.size() ) );
	}

	inline void MD5::update(const std::vector<char> &buf)
	{   md5_update( &context, reinterpret_cast<const uint8*>( &buf[0] ), static_cast<uint32>( buf.size() ) ); }

	inline void MD5::update(const char *buf, uint32 length)
	{   md5_update( &context, reinterpret_cast<const uint8*>( buf ), length );  }

	inline void MD5::finish(std::vector<char> &digest)
	{
		digest.resize( 16 );
		md5_finish( &context, reinterpret_cast<uint8*>( &digest[0] ) ); 
	}
}